//
// Created by thomas on 9/9/21.
//

#include "filecopy.h"

#include <QDebug>
#include <QFileInfo>
#include <QDir>

FileManageThread::FileManageThread() = default;

/**
 * 文件操作的准备工作，统计总的文件大小和文件列表，之后启动操作线程
 * @return
 */
int FileManageThread::operateStart(enum FILE_ACTION action)
{
    QString fileName;
    QDir fileDir;
    QStringList filter;
    QFileInfoList fileInfoList;
    QFileInfo fileInfo;
    int i = 0;

    // 检查目录路径
    fileInfo.setFile(mSrcPath);
    if (!fileInfo.isDir())
    {
        return ERROR_SRC_PATH_NULL;
    }

    if (action == FILE_ACTION_COPY)
    {
        fileInfo.setFile(mDesPath);
        if (!fileInfo.isDir())
        {
            return ERROR_DES_PATH_NULL;
        }
    }

    //设置过滤器和排序方式
    fileDir.setPath(mSrcPath);
    filter << "*.sd";   //设置过滤器，*.sd文件
    fileDir.setNameFilters(filter);
    fileDir.setFilter(QDir::Files | QDir::Hidden | QDir::NoSymLinks);   // 只选择文件其他的过滤掉
    fileDir.setSorting(QDir::Name);

    //统计所有符合规则的文件大小，并加入到文件链表
    mFileList.clear();
    mFileTotalSize = 0;
    mCurSize = 0;
    fileInfoList = fileDir.entryInfoList();     // 获取文件信息列表
    for (auto fitem: fileInfoList)
    {
        fitem = fileInfoList.at(i);
        mFileTotalSize += fitem.size();
        fileName = mSrcPath + "/" + fitem.fileName();
        mFileList << fileName;
        i++;
    }

    //没有符合的文件
    if (0 == mFileList.count())
    {
        return ERROR_NO_FILES;
    }

    //启动拷贝线程
    mAction = action;
    mbStop = false;
    emit operateStationSig(OPERATE_START, nullptr);
    this->start();
    return SUCCESS;
}

void FileManageThread::operateStop()
{
    mbStop = true;
}

/**
 * 执行文件操作的线程
 */
void FileManageThread::run()
{
    int i;
    QString fileName;
    QString qsStaText;

    for (i = 0; i < mFileList.count(); ++i)
    {
        fileName = mFileList.at(i);
        if (mAction == FILE_ACTION_COPY)
        {
            emit operateStationSig(OPERATE_FILE_NAME, fileName.split("/").last());
            if (ERROR_MEM_FULL == fileCopy(fileName))
            {
                mbStop = true;
                emit operateStationSig(OPERATE_ERROR_MEM_FULL, nullptr);
                this->exit();
                return;
            }
        }
        else if (mAction == FILE_ACTION_DEL)
        {
            emit operateStationSig(OPERATE_FILE_NAME, fileName.split("/").last());
            fileDelete(fileName);
            qsStaText = QString::number(100 * (i + 1) / mFileList.count());
            emit operateStationSig(OPERATE_DELETE_TOTAL_RATE, qsStaText);
        }

        if (mbStop)
        {
            break;
        }
    }

    emit operateStationSig(OPERATE_STOP, fileName);
}

/**
 * 单文件拷贝动作
 * @param fileName
 * @return
 */
int FileManageThread::fileCopy(const QString &fileName)
{
    QFileInfo fileInfo;
    QString desFileName;
    QByteArray byteArray;
    quint64 fileSize;
    QString qsStaText;
    quint64 count = 0;
    desFileName = mDesPath + "/" + fileName.split("/").last();
    fileInfo.setFile(fileName);
    fileSize = fileInfo.size();

    if (mFileTotalSize - mCurSize < fileSize)
    {
        return ERROR_MEM_FULL;
    }

    fileInfo.setFile(desFileName);
    if (fileInfo.isFile())                       // 存在则删除
    {
        QFile::remove(desFileName);
    }

    // 创建目标文件
    QFile desFile(desFileName);
    desFile.open(QIODevice::WriteOnly);
    // 打开原文件
    QFile srcFile(fileName);
    srcFile.open(QIODevice::ReadOnly);
    while (!srcFile.atEnd())
    {
        byteArray = srcFile.read(FILE_BLOCKSIZE);
        count += desFile.write(byteArray);
        qsStaText = QString::number(100 * count / fileSize);
        emit operateStationSig(OPERATE_COPY_SINGLE_RATE, qsStaText);
        qsStaText = QString::number(100 * (mCurSize + count) / mFileTotalSize);
        emit operateStationSig(OPERATE_COPY_TOTAL_RATE, qsStaText);
        if (mbStop)
        {
            desFile.close();
            srcFile.close();
            QFile::remove(desFileName);
            return SUCCESS;
        }
    }
    desFile.close();
    srcFile.close();
    mCurSize += fileSize;
    return SUCCESS;
}

/**
 * 单文件删除动作
 * @param fileName
 * @return
 */
int FileManageThread::fileDelete(const QString &fileName)
{
    QFileInfo fileInfo;

    fileInfo.setFile(fileName);
    if (fileInfo.isFile() && fileInfo.isWritable()) // 存在且可删除
    {
        QFile::remove(fileName);
    }

    return SUCCESS;
}